﻿using OpenTK.Graphics.OpenGL;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
using Silk.NET.SDL;
using System;
using System.Collections.Generic;
using System.Numerics;

public class RandomPointsWindow : GameWindow
{
    private List<Vector2> _points = new List<Vector2>();
    private Random _random = new Random();
    private int _vertexBufferObject;
    private int _vertexArrayObject;
    private Shader _shader;
    private Sdl _sdl;

    public RandomPointsWindow()
        : base(GameWindowSettings.Default,
              new NativeWindowSettings()
              {
                  Size = new OpenTK.Mathematics.Vector2i(800, 600),
                  Title = "随机点绘制 - SDL2 + OpenTK"
              })
    {
        // 初始化SDL（用于输入处理等）
        _sdl = Sdl.GetApi();
        _sdl.Init(Sdl.InitVideo | Sdl.InitEvents);
    }

    protected override void OnLoad()
    {
        base.OnLoad();

        // 初始化OpenGL
        GL.ClearColor(0.1f, 0.1f, 0.1f, 1.0f);

        // 创建着色器
        _shader = new Shader("shader.vert", "shader.frag");

        // 生成100个随机点
        GenerateRandomPoints(100);

        // 设置顶点缓冲
        _vertexArrayObject = GL.GenVertexArray();
        _vertexBufferObject = GL.GenBuffer();

        GL.BindVertexArray(_vertexArrayObject);
        GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject);

        // 设置顶点属性指针
        GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 2 * sizeof(float), 0);
        GL.EnableVertexAttribArray(0);

        // 初始上传数据
        UpdatePointBuffer();
    }

    private void GenerateRandomPoints(int count)
    {
        _points.Clear();
        for (int i = 0; i < count; i++)
        {
            _points.Add(new Vector2(
                (float)_random.NextDouble() * 2 - 1, // -1到1范围
                (float)_random.NextDouble() * 2 - 1
            ));
        }
    }

    private void UpdatePointBuffer()
    {
        // 将点数据转换为浮点数组
        float[] pointData = new float[_points.Count * 2];
        for (int i = 0; i < _points.Count; i++)
        {
            pointData[i * 2] = _points[i].X;
            pointData[i * 2 + 1] = _points[i].Y;
        }

        GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject);
        GL.BufferData(BufferTarget.ArrayBuffer, pointData.Length * sizeof(float), pointData, BufferUsageHint.DynamicDraw);
    }

    protected override void OnRenderFrame(FrameEventArgs e)
    {
        base.OnRenderFrame(e);

        GL.Clear(ClearBufferMask.ColorBufferBit);

        _shader.Use();
        GL.BindVertexArray(_vertexArrayObject);
        GL.DrawArrays(PrimitiveType.Points, 0, _points.Count);

        SwapBuffers();
    }

    protected override unsafe void OnUpdateFrame(FrameEventArgs e)
    {
        base.OnUpdateFrame(e);

        // 处理SDL事件
        Event sdlEvent;
        while (_sdl.PollEvent(&sdlEvent) != 0)
        {
            _sdl.Log("事件");
            switch (sdlEvent.Type)
            {
                case (uint)EventType.Quit:
                    Close();
                    break;

                case (uint)EventType.Keydown:
                    if (sdlEvent.Key.Keysym.Scancode == Scancode.ScancodeSpace)
                    {
                        GenerateRandomPoints(100);
                        UpdatePointBuffer();
                    }
                    else if (sdlEvent.Key.Keysym.Scancode == Scancode.ScancodeEscape)
                    {
                        Close();
                    }
                    break;
            }
        }
    }

    protected override void OnResize(ResizeEventArgs e)
    {
        base.OnResize(e);
        GL.Viewport(0, 0, e.Width, e.Height);
    }

    protected override void OnUnload()
    {
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        GL.DeleteBuffer(_vertexBufferObject);
        GL.DeleteVertexArray(_vertexArrayObject);
        _shader.Dispose();
        _sdl.Quit();
        base.OnUnload();
    }
}

// 简单的着色器类
public class Shader : IDisposable
{
    private int _handle;

    public Shader(string vertPath, string fragPath)
    {
        // 顶点着色器
        string vertSource = @"#version 330 core
            layout (location = 0) in vec2 aPosition;
            void main()
            {
                gl_Position = vec4(aPosition, 0.0, 1.0);
                gl_PointSize = 8.0;
            }";

        // 片段着色器
        string fragSource = @"#version 330 core
            out vec4 FragColor;
            void main()
            {
                FragColor = vec4(0.8, 0.3, 0.2, 1.0);
            }";

        int vertexShader = GL.CreateShader(ShaderType.VertexShader);
        GL.ShaderSource(vertexShader, vertSource);
        GL.CompileShader(vertexShader);

        int fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
        GL.ShaderSource(fragmentShader, fragSource);
        GL.CompileShader(fragmentShader);

        _handle = GL.CreateProgram();
        GL.AttachShader(_handle, vertexShader);
        GL.AttachShader(_handle, fragmentShader);
        GL.LinkProgram(_handle);

        GL.DeleteShader(vertexShader);
        GL.DeleteShader(fragmentShader);
    }

    public void Use()
    {
        GL.UseProgram(_handle);
    }

    public void Dispose()
    {
        GL.DeleteProgram(_handle);
    }
}

// 程序入口
class Program
{
    static void Main(string[] args)
    {
        using var window = new RandomPointsWindow();
        window.Run();
    }
}